using UnityEngine;
using UnityEngine.UI;

#if UNITY_EDITOR
using UnityEditor;
#endif

// 扩展ContentSizeFitter类，以便可以设置最大宽度和高度
public class ContentSizeFitterExp : ContentSizeFitter
{
    // 最大宽度，-1表示无限制
    [SerializeField] private float m_MaxWidth = -1;

    // 最大宽度的公开属性
    public float maxWdith
    {
        get => m_MaxWidth;
        set
        {
            m_MaxWidth = value;
            SetDirty(); // 当最大宽度改变时，标记为需要重新布局
        }
    }

    // 最大高度，-1表示无限制
    [SerializeField] private float m_MaxHeight = -1;

    // 最大高度的公开属性
    public float maxHeight
    {
        get => m_MaxHeight;
        set
        {
            m_MaxHeight = value;
            SetDirty(); // 当最大高度改变时，标记为需要重新布局
        }
    }

    // RectTransform组件的缓存
    [System.NonSerialized] private RectTransform m_Rect;
    private RectTransform rectTransform
    {
        get
        {
            if (m_Rect == null)
                m_Rect = GetComponent<RectTransform>();
            return m_Rect;
        }
    }

    // 用于跟踪DrivenTransform的变化
    private DrivenRectTransformTracker m_Tracker;

    // 禁用时清除跟踪器并标记布局需要重建
    protected override void OnDisable()
    {
        m_Tracker.Clear();
        LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
    }

    // 处理自适应大小的方法，根据轴向和最大值进行处理
    private void HandleSelfFittingAlongAxis(int axis)
    {
        FitMode fitting = (axis == 0 ? horizontalFit : verticalFit);
        if (fitting == FitMode.Unconstrained)
        {
            m_Tracker.Add(this, rectTransform, DrivenTransformProperties.None);
            return;
        }

        m_Tracker.Add(this, rectTransform,
            (axis == 0 ? DrivenTransformProperties.SizeDeltaX : DrivenTransformProperties.SizeDeltaY));

        var maxValue = axis == 0 ? m_MaxWidth : m_MaxHeight;
        if (fitting == FitMode.MinSize)
            rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis,
                maxValue >= 0
                    ? Mathf.Min(LayoutUtility.GetMinSize(m_Rect, axis), maxValue)
                    : LayoutUtility.GetMinSize(m_Rect, axis));
        else
            rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis,
                maxValue >= 0
                    ? Mathf.Min(LayoutUtility.GetPreferredSize(m_Rect, axis), maxValue)
                    : LayoutUtility.GetPreferredSize(m_Rect, axis));
    }

    // 设置水平布局
    public override void SetLayoutHorizontal()
    {
        m_Tracker.Clear();
        HandleSelfFittingAlongAxis(0);
    }

    // 设置垂直布局
    public override void SetLayoutVertical()
    {
        HandleSelfFittingAlongAxis(1);
    }
}

#if UNITY_EDITOR

// 自定义ContentSizeFitterExp的Inspector面板
[CustomEditor(typeof(ContentSizeFitterExp))]
public class ContentSizeFitterExpInspector : UnityEditor.UI.ContentSizeFitterEditor
{
    // 定义需要在Inspector面板中显示的属性
    SerializedProperty m_HorizontalFit;
    SerializedProperty m_VerticalFit;
    SerializedProperty m_MaxWidth;
    SerializedProperty m_MaxHeight;

    // 在Inspector面板启用时，获取需要显示的属性
    protected override void OnEnable()
    {
        base.OnEnable();
        m_HorizontalFit = serializedObject.FindProperty("m_HorizontalFit");
        m_VerticalFit = serializedObject.FindProperty("m_VerticalFit");
        m_MaxWidth = serializedObject.FindProperty("m_MaxWidth");
        m_MaxHeight = serializedObject.FindProperty("m_MaxHeight");
    }

    // 自定义Inspector面板的GUI
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        serializedObject.Update();
        if (m_HorizontalFit.enumValueIndex != 0)
            LayoutElementField(m_MaxWidth, 0, new GUIContent("最大宽度"));
        if (m_VerticalFit.enumValueIndex != 0)
            LayoutElementField(m_MaxHeight, 0, new GUIContent("最大高度"));
        serializedObject.ApplyModifiedProperties();
    }

    // 显示属性字段
    void LayoutElementField(SerializedProperty property, float defaultValue, GUIContent rawLabel)
    {
        LayoutElementField(property, _ => defaultValue, rawLabel);
    }

    // 显示属性字段，并提供默认值
    void LayoutElementField(SerializedProperty property, System.Func<RectTransform, float> defaultValue,
        GUIContent rawLabel)
    {
        Rect position = EditorGUILayout.GetControlRect();

        // 创建标签
        GUIContent label = EditorGUI.BeginProperty(position, rawLabel, property);

        // 创建字段位置
        Rect fieldPosition = EditorGUI.PrefixLabel(position, label);

        // 创建复选框位置
        Rect toggleRect = fieldPosition;
        toggleRect.width = 16;

        // 创建浮点数字段位置
        Rect floatFieldRect = fieldPosition;
        floatFieldRect.xMin += 16;

        // 创建复选框，用于启用或禁用属性
        EditorGUI.BeginChangeCheck();
        bool enabled = EditorGUI.ToggleLeft(toggleRect, GUIContent.none, property.floatValue >= 0);
        if (EditorGUI.EndChangeCheck())
        {
            // 如果复选框状态改变，更新属性值
            property.floatValue =
                (enabled ? defaultValue((target as ContentSizeFitterExp).transform as RectTransform) : -1);
        }

        if (!property.hasMultipleDifferentValues && property.floatValue >= 0)
        {
            // 创建浮点数字段，用于输入属性值
            EditorGUIUtility.labelWidth = 4; // Small invisible label area for drag zone functionality
            EditorGUI.BeginChangeCheck();
            float newValue = EditorGUI.FloatField(floatFieldRect, new GUIContent(" "), property.floatValue);
            if (EditorGUI.EndChangeCheck())
            {
                // 如果输入的值改变，更新属性值
                property.floatValue = Mathf.Max(0, newValue);
            }

            EditorGUIUtility.labelWidth = 0;
        }

        // 结束属性显示
        EditorGUI.EndProperty();
    }
}
#endif